<template>
    <div class="page-main beautiful-scrollbar">
        <h1 class="page-title">映射器</h1>

        <!-- 映射器选择器 -->
        <div class="px-4">
            <v-select
                :label="`当前映射器（${mapper.now.name}）`"
                :model-value="mapper.name === '' ? EmptyText : mapper.name"
                @update:model-value="setMapperName"
                :items="[EmptyText, ...mapper.all]"
            >
                <template v-slot:append>
                    <!-- 新建映射器 -->
                    <v-btn
                        style="background-color: transparent"
                        @click="openDialog(DialogKind.New)"
                        icon
                        :elevation="2"
                    >
                        <v-icon>mdi-plus</v-icon>
                        <v-tooltip activator="parent" location="top">新建映射器</v-tooltip>
                    </v-btn>

                    <!-- 复制映射器 -->
                    <v-btn
                        class="ms-2"
                        style="background-color: transparent"
                        @click="openDialog(DialogKind.Copy)"
                        :disabled="mapper.name === ''"
                        icon
                    >
                        <v-icon>mdi-content-copy</v-icon>
                        <v-tooltip activator="parent" location="top">复制映射器</v-tooltip>
                    </v-btn>

                    <!-- 重命名映射器 -->
                    <v-btn
                        class="ms-2"
                        style="background-color: transparent"
                        @click="openDialog(DialogKind.Rename)"
                        :disabled="mapper.name === ''"
                        icon
                    >
                        <v-icon>mdi-rename-outline</v-icon>
                        <v-tooltip activator="parent" location="top">重命名映射器</v-tooltip>
                    </v-btn>

                    <!-- 删除映射器 -->
                    <v-btn
                        class="ms-2"
                        style="background-color: transparent"
                        @click="openDialog(DialogKind.Delete)"
                        :disabled="mapper.name === ''"
                        icon
                    >
                        <v-icon>mdi-trash-can-outline</v-icon>
                        <v-tooltip activator="parent" location="top">删除映射器</v-tooltip>
                    </v-btn>
                </template>
            </v-select>
        </div>

        <div class="mb-6 px-4 mapper-setter">
            <!-- 每种类型映射器独有的页面 -->
            <router-view v-slot="{ Component }">
                <v-fade-transition>
                    <component :is="Component" />
                </v-fade-transition>
            </router-view>

            <!-- 作者信息 -->
            <author-info class="mt-8 mb-4"></author-info>
        </div>

        <!-- 映射器操作对话框 -->
        <confirm-dialog
            v-model="dialogState"
            :title="dialogTitle"
            @confirm="toConfirmDialog"
            @cancel="dialogState = false"
        >
            <!-- 新建、复制或重命名映射器时，设置名称 -->
            <v-text-field v-if="dialogKind !== DialogKind.Delete" v-model="newMapperName" label="映射器名称">
                <template #append-inner>
                    <v-fade-transition>
                        <span
                            v-if="originalMapperName !== newMapperName"
                            style="cursor: pointer"
                            @click="newMapperName = originalMapperName"
                        >
                            <v-icon>mdi-undo-variant</v-icon>
                            <v-tooltip activator="parent" location="bottom">撤回</v-tooltip>
                        </span>
                    </v-fade-transition>
                </template>
            </v-text-field>

            <!-- 新建映射器的类型 -->
            <v-select
                v-if="dialogKind === DialogKind.New"
                :items="templateNames"
                v-model="nowTemplate"
                label="映射器类型"
            ></v-select>

            <!-- 删除映射器提醒文本 -->
            <p
                v-if="dialogKind === DialogKind.Delete"
                class="mb-6 text-medium-emphasis text-body-1"
                style="user-select: none"
            >
                是否确定要删除映射器“{{ originalMapperName }}”？
            </p>
        </confirm-dialog>
    </div>
</template>

<script setup lang="ts">
import { ref, computed, watch } from "vue";
import { useRouter } from "vue-router";
import type { MapperConfig } from "@/lib/api";
import { injectMessageState } from "@/lib/view";
import { EmptyText, MapperTemplates } from "@/lib/constants";
import useMapperStore from "@/store/mapper";
import ConfirmDialog from "@/components/public/dialog/ConfirmDialog.vue";
import AuthorInfo from "@/components/public/info/AuthorInfo.vue";

const router = useRouter();

const mapper = useMapperStore();

// 重新路由
watch(
    () => mapper.now.name,
    (name) => {
        let path: string = name;
        if (name.endsWith("Mapper")) {
            path = name.slice(0, -6);
        }
        router.replace(`/mapper/${path}`);
    },
    { immediate: true },
);

// 当前是哪种对话框
enum DialogKind {
    New,
    Copy,
    Rename,
    Delete,
}

// 对话框属性
const dialogState = ref(false);
const dialogKind = ref(DialogKind.New);
const dialogTitle = computed(() => {
    switch (dialogKind.value) {
        case DialogKind.New:
            return "新建映射器";
        case DialogKind.Copy:
            return "复制映射器";
        case DialogKind.Rename:
            return "重命名映射器";
        case DialogKind.Delete:
            return "删除映射器";
    }
});

// 全局消息状态
const messageState = injectMessageState();

// 映射器模板
const templateNames = MapperTemplates.map(([desc, mapper]) => `${desc}（${mapper.name}）`);
const templates = new Map<string, MapperConfig>();
for (let i = 0; i < templateNames.length; ++i) {
    templates.set(templateNames[i], MapperTemplates[i][1]);
}
const nowTemplate = ref(templateNames[0]);

// 映射器的名称
const originalMapperName = ref("");
const newMapperName = ref("");

/**
 * 设置映射器名称
 * @param value 映射器名称值
 */
async function setMapperName(value: string) {
    if (value === EmptyText) {
        await mapper.setName("");
    } else {
        await mapper.setName(value);
    }
}

/**
 * 打开对话框
 * @param kind 对话框的类型
 */
function openDialog(kind: DialogKind) {
    // 根据类型设置对话框参数
    switch (kind) {
        case DialogKind.New:
            originalMapperName.value = "";
            newMapperName.value = "";
            break;
        case DialogKind.Copy:
        case DialogKind.Rename:
            originalMapperName.value = mapper.name;
            newMapperName.value = mapper.name;
            break;
        case DialogKind.Delete:
            originalMapperName.value = mapper.name;
            break;
    }

    dialogKind.value = kind;
    dialogState.value = true;
}

/**
 * 添加映射器
 */
async function addMapper() {
    if (newMapperName.value === "") {
        showMessage("映射器名称不能为空");
        return;
    }

    const template = templates.get(nowTemplate.value);
    if (template === undefined) {
        showMessage(`映射器类型 “${nowTemplate.value}” 不存在`);
        return;
    }

    if (mapper.set.has(newMapperName.value)) {
        showMessage(`映射器 “${newMapperName.value}” 已存在`);
        return;
    }

    dialogState.value = false;
    const res = await mapper.add(newMapperName.value, template);

    if (res) {
        showMessage(`新建映射器 “${newMapperName.value}” 成功`);
        await mapper.setName(newMapperName.value);
    } else {
        showMessage(`新建映射器 “${newMapperName.value}” 失败`);
    }
}

/**
 * 复制映射器
 */
async function copyMapper() {
    if (newMapperName.value === "") {
        showMessage("映射器名称不能为空");
        return;
    }

    if (mapper.set.has(newMapperName.value)) {
        showMessage(`映射器 “${newMapperName.value}” 已存在`);
        return;
    }

    dialogState.value = false;
    const res = await mapper.add(newMapperName.value, mapper.now);

    if (res) {
        showMessage(`复制映射器 “${newMapperName.value}” 成功`);
        await mapper.setName(newMapperName.value);
    } else {
        showMessage(`复制映射器 “${newMapperName.value}” 失败`);
    }
}

/**
 * 重命名映射器
 */
async function renameMapper() {
    if (originalMapperName.value === "") {
        showMessage("不能重命名默认映射器");
        return;
    }

    if (mapper.set.has(newMapperName.value)) {
        showMessage(`映射器 “${newMapperName.value}” 已存在`);
    }

    dialogState.value = false;
    const res = await mapper.rename(originalMapperName.value, newMapperName.value);

    if (res) {
        showMessage(`映射器 “${originalMapperName.value}” 已重命名为 “${newMapperName.value}”`);
    } else {
        showMessage(`映射器 “${originalMapperName.value}” 重命名失败`);
    }
}

/**
 * 删除映射器
 */
async function deleteMapper() {
    if (mapper.name === "") {
        showMessage("不能删除默认映射器");
        return;
    }

    if (!mapper.set.has(mapper.name)) {
        showMessage(`映射器 “${mapper.name}” 不存在`);
        return;
    }

    const name = mapper.name;
    dialogState.value = false;
    const res = await mapper.remove(mapper.name);

    if (res) {
        showMessage(`删除映射器 “${name}” 成功`);
    } else {
        showMessage(`删除映射器 “${name}” 失败`);
    }
}

/**
 * 确认对话框
 */
function toConfirmDialog() {
    switch (dialogKind.value) {
        case DialogKind.New:
            addMapper();
            break;
        case DialogKind.Copy:
            copyMapper();
            break;
        case DialogKind.Rename:
            renameMapper();
            break;
        case DialogKind.Delete:
            deleteMapper();
            break;
    }
}

/**
 * 显示消息
 * @param message 消息
 */
function showMessage(message: string) {
    messageState.visible = true;
    messageState.text = message;
}
</script>

<style scoped lang="scss">
.mapper-setter {
    overflow-y: scroll;
}
</style>
